﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Web.UI.WebControls;

namespace GoodStuff.Web.Controls
{
    /// <summary>
    /// Extenstion which can be used on a System.Web.UI.WebControls.TextBox
    /// </summary>
    public static class TextboxExtensions
    {
        public const string dutchCulture = "nl-NL";

        /// <summary>
        /// Convert a input from a textbox to a DateTime object. It throws on invalid input. Uses the nl-NL culture by default
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static DateTime? TextAsDateNullable(this TextBox textbox)
        {
            return TextAsDateNullable(textbox, System.Globalization.CultureInfo.GetCultureInfo(TextboxExtensions.dutchCulture));
        }

        /// <summary>
        /// Convert a input from a textbox to a DateTime object. It throws on invalid input
        /// </summary>
        /// <param name="textbox"></param>
        /// <param name="culture">Spefic culture</param>
        /// <returns></returns>
        public static DateTime? TextAsDateNullable(this TextBox textbox, CultureInfo culture)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                return null;

            DateTime result;
            if (DateTime.TryParse(textbox.Text, out result))
            {
                return DateTime.ParseExact(textbox.Text, culture.DateTimeFormat.ShortDatePattern, culture);
            }
            else
            {
                throw new System.FormatException("Invalid input for converting to datetime for TextBox with ID " + textbox.ID);
            }
        }

        /// <summary>
        /// Convert a input from a textbox to a (optional) DateTime object. It throws on invalid input. Dateformat (dd-MM-yyyy, nl-NL culture)
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static DateTime TextAsDate(this TextBox textbox)
        {
            return TextAsDate(textbox, CultureInfo.GetCultureInfo(TextboxExtensions.dutchCulture));
        }

        /// <summary>
        /// Convert a input from a textbox to a (optional) DateTime object. It throws on invalid input. Dateformat is based on "ShortDatePattern" of the given culture
        /// </summary>
        /// <param name="textbox"></param>
        /// <param name="culture">specific culture</param>
        /// <returns></returns>
        public static DateTime TextAsDate(this TextBox textbox, CultureInfo culture)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                throw new ArgumentException("Cannot convert a null or empty string to non nullable datetime for textbox with ID " + textbox.ID, "Text");

            DateTime result;
            if (DateTime.TryParse(textbox.Text, out result))
            {
                return DateTime.ParseExact(textbox.Text, culture.DateTimeFormat.ShortDatePattern, culture);
            }
            else
            {
                throw new System.FormatException("Invalid input for converting to datetime for textbox with ID " + textbox.ID);
            }
        }

        /// <summary>
        /// Convert a input from a textbox to an (optional) Integer (Int32) object. 
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static int? TextAsIntegerNullabe(this TextBox textbox)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                return null;

            int result;
            if (int.TryParse(textbox.Text, out result))
            {
                return result;
            }
            else
            {
                throw new System.FormatException("Invalid input for converting to Int32 for textbox with ID " + textbox.ID);
            }
        }

        /// <summary>
        /// Convert a input from a textbox to an Integer (Int32) object. 
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static int TextAsInteger(this TextBox textbox)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                throw new ArgumentException(string.Format("Value cannot be null for converting to Int32 for Textbox with ID '{0}'", textbox.ID), "Text");

            int result;
            if (int.TryParse(textbox.Text, out result))
            {
                return result;
            }
            else
            {
                throw new ArgumentException(string.Format("Value is not numeric or too large for converting to Int32 for Textbox with ID '{0}'", textbox.ID), "Text");
            }
        }

        /// <summary>
        /// Convert a input from a textbox to an (optional) Long (Int64) object. 
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static long? TextAsLongNullabe(this TextBox textbox)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                return null;

            long result;
            if (long.TryParse(textbox.Text, out result))
            {
                return result;
            }
            else
            {
                throw new System.FormatException("Invalid input for converting to Int64 for textbox with ID " + textbox.ID);
            }
        }

        /// <summary>
        /// Convert a input from a textbox to an Long (Int64) object. 
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static long TextAsLong(this TextBox textbox)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                throw new ArgumentException(string.Format("Value cannot be null for converting to Int64 for Textbox with ID '{0}'", textbox.ID), "Text");

            long result;
            if (long.TryParse(textbox.Text, out result))
            {
                return result;
            }
            else
            {
                throw new ArgumentException(string.Format("Value is not numeric or too large for converting to Int64 for Textbox with ID '{0}'", textbox.ID), "Text");
            }
        }

        /// <summary>
        /// Convert a input from a textbox to a (optional) GUID object. 
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static Guid? TextAsGuidNullable(this TextBox textbox)
        {
            if (string.IsNullOrEmpty(textbox.Text))
            {
                return null;
            }
            else
            {
                try
                {
                    return new Guid(textbox.Text); //could throw
                }
                catch (Exception ex)
                {
                    throw new ArgumentException("Input of textbox couldn't be converted to a GUID. Textbox with ID " + textbox.ID, "Text", ex);
                }
            }
        }

        /// <summary>
        /// Convert a input from a textbox to a decimal object. It throws on invalid input. Uses the nl-NL culture by default
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static decimal? TextAsDecimalNullable(this TextBox textbox)
        {
            return TextAsDecimalNullable(textbox, System.Globalization.CultureInfo.GetCultureInfo(TextboxExtensions.dutchCulture));
        }

        /// <summary>
        /// Convert a input from a textbox to a decimal object. It throws on invalid input
        /// </summary>
        /// <param name="textbox"></param>
        /// <param name="culture">specific culture</param>
        /// <returns></returns>
        public static decimal? TextAsDecimalNullable(this TextBox textbox, CultureInfo culture)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                return null;

            decimal result;
            if (decimal.TryParse(textbox.Text, out result))
            {
                return decimal.Parse(textbox.Text, NumberStyles.Number, culture);
            }
            else
            {
                throw new System.FormatException("Invalid input for converting to decimal for TextBox with ID " + textbox.ID);
            }
        }

        /// <summary>
        /// Convert a input from a textbox to a (optional) decimal object. It throws on invalid input. Seperator is used from the nl-NL culture
        /// </summary>
        /// <param name="textbox"></param>
        /// <returns></returns>
        public static decimal TextAsDecimal(this TextBox textbox)
        {
            return TextAsDecimal(textbox, CultureInfo.GetCultureInfo(TextboxExtensions.dutchCulture));
        }

        /// <summary>
        /// Convert a input from a textbox to a (optional) decimal object. It throws on invalid input. Seperator is based on the given culture
        /// </summary>
        /// <param name="textbox"></param>
        /// <param name="culture">specific culture</param>
        /// <returns></returns>
        public static decimal TextAsDecimal(this TextBox textbox, CultureInfo culture)
        {
            if (string.IsNullOrEmpty(textbox.Text))
                throw new ArgumentException("Cannot convert a null or empty string to non nullable decimal for textbox with ID " + textbox.ID, "Text");

            decimal result;
            if (decimal.TryParse(textbox.Text, out result))
            {
                return decimal.Parse(textbox.Text, NumberStyles.Number, culture);
            }
            else
            {
                throw new System.FormatException("Invalid input for converting to decimal for textbox with ID " + textbox.ID);
            }
        }
        
    }
}
